package com.kim.smartring.activity;

import android.app.Activity;
import android.app.ListActivity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ListView;
import android.widget.Toast;

import com.kim.smartring.R;
import com.kim.smartring.adapter.DevicesAdapter;
import com.kim.smartring.ble.BleWrapper;
import com.kim.smartring.ble.BleWrapperUiCallbacks;

/**
 * 手环设备列表
 * 
 * @author Huang
 * 
 */
public class DeviceActivity extends ListActivity {

	private static final long SCANNING_TIMEOUT = 10 * 1000l; // 设备搜索超时时间 10秒钟
	private static final int ENABLE_BT_REQUEST_ID = 1; //

	private boolean mScanning = false;
	private BleWrapper mBleWrapper = null;
	private DevicesAdapter mDevicesAdapter;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		initParam();
	}

	@Override
	protected void onResume() {
		super.onResume();
		// on every Resume check if BT is enabled (user could turn it off while
		// app was in background etc.)
		if (mBleWrapper.isBtEnabled() == false) {
			// BT is not turned on - ask user to make it enabled
			Intent enableBtIntent = new Intent(
					BluetoothAdapter.ACTION_REQUEST_ENABLE);
			startActivityForResult(enableBtIntent, ENABLE_BT_REQUEST_ID);
			// see onActivityResult to check what is the status of our request
		}

		// initialize BleWrapper object
		mBleWrapper.initialize();

		mDevicesAdapter = new DevicesAdapter(this);
		setListAdapter(mDevicesAdapter);

		// Automatically start scanning for devices
		mScanning = true;
		// remember to add timeout for scanning to not run it forever and drain
		// the battery
		addScanningTimeout();
		mBleWrapper.startScanning();
		invalidateOptionsMenu();
	}

	@Override
	protected void onPause() {
		super.onPause();
		mScanning = false;
		mBleWrapper.stopScanning();
		invalidateOptionsMenu();
		mDevicesAdapter.clearList();
	};

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.scanning, menu);

		if (mScanning) {
			menu.findItem(R.id.scanning_start).setVisible(false);
			menu.findItem(R.id.scanning_stop).setVisible(true);
			menu.findItem(R.id.scanning_indicator).setActionView(
					R.layout.progress_indicator);

		} else {
			menu.findItem(R.id.scanning_start).setVisible(true);
			menu.findItem(R.id.scanning_stop).setVisible(false);
			menu.findItem(R.id.scanning_indicator).setActionView(null);
		}
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.scanning_start:
			mScanning = true;
			mBleWrapper.startScanning();
			break;
		case R.id.scanning_stop:
			mScanning = false;
			mBleWrapper.stopScanning();
			break;
		}

		invalidateOptionsMenu();
		return true;
	}

	/* user has selected one of the device */
	@Override
	protected void onListItemClick(ListView l, View v, int position, long id) {
		final BluetoothDevice device = mDevicesAdapter.getDevice(position);
		if (device == null)
			return;

		final Intent intent = new Intent(this, PeripheralActivity.class);
		intent.putExtra(PeripheralActivity.EXTRAS_DEVICE_NAME, device.getName());
		intent.putExtra(PeripheralActivity.EXTRAS_DEVICE_ADDRESS,
				device.getAddress());
		intent.putExtra(PeripheralActivity.EXTRAS_DEVICE_RSSI,
				mDevicesAdapter.getRssi(position));

		if (mScanning) {
			mScanning = false;
			invalidateOptionsMenu();
			mBleWrapper.stopScanning();
		}

		startActivity(intent);
	}

	/* check if user agreed to enable BT */
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		// user didn't want to turn on BT
		if (requestCode == ENABLE_BT_REQUEST_ID) {
			if (resultCode == Activity.RESULT_CANCELED) {
				btDisabled();
				return;
			}
		}
		super.onActivityResult(requestCode, resultCode, data);
	}

	private void initParam() {
		// create BleWrapper with empty callback object except uiDeficeFound
		// function (we need only that here)
		mBleWrapper = new BleWrapper(this, new BleWrapperUiCallbacks.Null() {
			@Override
			public void uiDeviceFound(final BluetoothDevice device,
					final int rssi, final byte[] record) {
				handleFoundDevice(device, rssi, record);
			}
		});

		// check if we have BT and BLE on board
		if (mBleWrapper.checkBleHardwareAvailable() == false) {
			bleMissing();
		}
	}

	/* add device to the current list of devices */
	private void handleFoundDevice(final BluetoothDevice device,
			final int rssi, final byte[] scanRecord) {
		// adding to the UI have to happen in UI thread
		runOnUiThread(new Runnable() {
			@Override
			public void run() {
				mDevicesAdapter.addDevice(device, rssi, scanRecord);
				mDevicesAdapter.notifyDataSetChanged();
			}
		});
	}

	/*
	 * make sure that potential scanning will take no longer than
	 * <SCANNING_TIMEOUT> seconds from now on
	 */
	private void addScanningTimeout() {
		Runnable timeout = new Runnable() {
			@Override
			public void run() {
				if (mBleWrapper == null)
					return;
				mScanning = false;
				mBleWrapper.stopScanning();
				invalidateOptionsMenu();
			}
		};
		new Handler().postDelayed(timeout, SCANNING_TIMEOUT);
	}

	private void btDisabled() {
		Toast.makeText(this, "Sorry, BT has to be turned ON for us to work!",
				Toast.LENGTH_LONG).show();
		finish();
	}

	private void bleMissing() {
		Toast.makeText(this, "BLE Hardware is required but not available!",
				Toast.LENGTH_LONG).show();
		finish();
	}
}
